﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using Fany.Libs.AsynchSocketLib;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Net;
using System.Xml;
using System.Runtime.InteropServices;

namespace AMStudio.Driver
{
    public delegate void RemoteRunnerEvents_OnClose(object objRunner);
    public delegate void RemoteRunnerEvents_OnNewCommand(object objRunner, string txCommand);

    class RemoteRunner
    {
        private TcpClient m_TcpClient = null;
        private Thread m_Session = null;
        private string m_IP = "";
        private int m_Port = 0;

        public RemoteRunner(TcpClient objClient)
        {
            m_TcpClient = objClient;
        }

        public bool IsRunning
        {
            get{ return m_Session != null && m_Session.IsAlive;}
        }

        public string IP
        {
            get {return m_IP;}
        }

        public int Port
        {
            get { return m_Port; }
        }
        
        public bool Start()
        {
            if (IsRunning)
            {
                return true;
            }

            try
            {
                ManualResetEvent _Event = new ManualResetEvent(false);
                bool _Success = false;

                try
                {
                    m_Session = new Thread(new ParameterizedThreadStart(RemoteSession));
                    m_Session.Start(_Event);

                    try
                    {
                        while (!_Event.WaitOne(0) && m_Session.IsAlive)
                        {
                            Thread.Sleep(20);
                        }
                    }
                    catch
                    {
                        m_Session.Abort();
                        m_Session.Join();
                        throw;
                    }

                    _Success = m_Session.IsAlive;
                }
                catch
                {
                }

                if (!_Success)
                {
                    m_Session = null;
                }
                return _Success;
            }
            catch
            {
            }
            return false;
        }

        public bool Stop()
        {
            if (m_TcpClient != null)
            {
                m_TcpClient.Close();
            }

            if (!IsRunning)
            {
            }
            else
            {
                m_Session.Join();
            }

            m_TcpClient = null;
            m_Session = null;
            return true;
        }

        public event RemoteRunnerEvents_OnClose CloseEventHandler;

        protected virtual void onCloseEventHandler(object objRunner)
        {
            if (CloseEventHandler != null)
            {
                CloseEventHandler(objRunner);
            }
        }

        public event RemoteRunnerEvents_OnNewCommand NewCommandEventHandler;

        protected virtual void OnNewCommandEventHandler(object objRunner, string txCommand)
        {
            if (NewCommandEventHandler != null)
            {
                NewCommandEventHandler(objRunner, txCommand);
            }
        }

        private void RemoteSession(Object client)
        {
            ManualResetEvent _Ready = (ManualResetEvent)client;

            try
            {
                Thread.CurrentThread.IsBackground = false;

                uint dummy = 0;
                byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
                BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
                BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
                BitConverter.GetBytes((uint)5000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);

                Socket socket = m_TcpClient.Client;
                IPEndPoint _EndPoint = (IPEndPoint)socket.RemoteEndPoint;

                m_IP = _EndPoint.Address.ToString();
                m_Port = _EndPoint.Port;

                socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
                _Ready.Set();

                while(true)
                {
                    byte[] _Buffer = new byte[m_TcpClient.ReceiveBufferSize];
                    int _Readed = socket.Receive(_Buffer, 0, _Buffer.Length, SocketFlags.None);

                    if (_Readed == 0)
                    {
                        break;
                    }

                    ASCIIEncoding encoder = new ASCIIEncoding();
                    string m_Commands = encoder.GetString(_Buffer, 0, _Readed);
                    m_Commands = m_Commands.Trim();
                    m_Commands = m_Commands.TrimEnd(new char[] { '\r', '\n' });
                    OnNewCommandEventHandler(this, m_Commands);
                }
            }
            catch
            {
            }

            onCloseEventHandler(this);
        }
    }

    public class CognexDriverL : IDisposable
    {
        public delegate void RemoteRunnerEvents_OnNewCommand(string txCommand);

        protected ExceptionManager ExManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

        //private DefaultTraceListener DebugConsole = new DefaultTraceListener();
        private Process process = Process.GetCurrentProcess();

        private string ip_address = "127.0.0.1";
        private int tcp_port = 0;
        private Socket sock;
        private ClientInfo client;
        private bool connected = false;
        private string user = "admin";
        private string password = "admin";
        private XmlNodeReader lastResponseReader;
        private string mLastResponseString;

        public delegate void CameraDataReceivedHandler(object sender, CameraArgsL e);
        public event CameraDataReceivedHandler OnDataReceived;

        public delegate void CameraConnectClosedHandler(object sender, EventArgs e);
        public event CameraConnectClosedHandler OnConnectClosed;

        public delegate void CameraConnectedHandler(object sender, EventArgs e);
        public event CameraConnectedHandler OnConnected;
        //private bool disposed = false;

        public CognexDriverL()
        {

        }

        public CognexDriverL(string ip_s, int p_n, string usr, string pa, int portS)
            : this()
        {
            ip_address = ip_s;
            tcp_port = p_n;
            user = usr;
            password = pa;
            tcp_portS = portS;
        }


        public bool Initialize()
        {
            bool ret = false;
            try
            {

                if (!Open())
                {
                    return false;
                }

                if (OnConnected != null)
                {
                    OnConnected(this, new EventArgs());
                }

                ret = true;
            }
            catch (Exception ex)
            {
                //_Last_Error_Code = ErrorCodeNum.PressNotInit;
                string sName = this.GetType().FullName;
                ExManager.HandleException(ex, "Policy");
            }

            return ret;
        }



        public bool Open()
        {
            Stop();

            if (!Start())
            {
                return false;
            }

            sock = Sockets.CreateTCPSocket(ip_address, tcp_port, true);
            

            byte[] buffer1 = Encoding.ASCII.GetBytes(user + "\r\n");
            byte[] buffer2 = Encoding.ASCII.GetBytes(password + "\r\n");
            byte[] buffer3 = new byte[0x100];
            int num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
            string text1 = Encoding.ASCII.GetString(buffer3, 0, num1);
            int num2 = text1.IndexOf("User: "); //Strings.NL("User: "));
            if (num2 < 0)
            {
                num2 = text1.IndexOf("Welcome"); //Strings.NL("Welcome"));
                if (num2 >= 0)
                {
                    num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
                    text1 = text1 + Encoding.ASCII.GetString(buffer3, 0, num1);
                    num2 = text1.IndexOf("User: ", num2);  //Strings.NL("User: "), num2);
                }
            }
            if (num2 < 0)
            {
                throw new Exception();
            }
            this.sock.Send(buffer1, buffer1.Length, SocketFlags.None);
            num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
            text1 = text1 + Encoding.ASCII.GetString(buffer3, 0, num1);
            num2 = text1.IndexOf("Password: ", num2); //Strings.NL("Password: "), num2);
            if (num2 < 0)
            {
                throw new Exception("Invalid Username"); //Strings.InvalidUsername(), true);
            }
            this.sock.Send(buffer2, buffer2.Length, SocketFlags.None);
            num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
            num2 = (text1 + Encoding.ASCII.GetString(buffer3, 0, num1)).IndexOf("User Logged In\r\n", num2); //Strings.NL("User Logged In\r\n"), num2);
            if (num2 < 0)
            {
                throw new Exception("Invalid Password"); //Strings.InvalidPassword(), false);
            }

            
            //    /*
            //    Command: GET FILELIST

            //    <Response>
            //    <Status>1</Status>
            //    <NumFiles>1</NumFiles>
            //    <FileName ID="0">main.job</FileName>
            //    </Response>
            //    */

            client = new ClientInfo(sock, false); // Don't start receiving yet
            client.OnReadBytes += new ConnectionReadBytes(ReadData);
            client.OnClose += new ConnectionClosed(client_OnClose);
            client.BeginReceive();

            SendCommand("PUT XML 2\r\n",string.Empty);
            connected = true;

            return true;
        }

        private void client_OnClose(ClientInfo ci)
        {
            try
            {
//                 Close();

                if (OnConnectClosed != null)
                {
                    EventArgs arg = new EventArgs();
                    OnConnectClosed(this, arg);
                }
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            //if (!this.disposed)
            //{
            //    // If disposing equals true, dispose all managed 
            //    // and unmanaged resources.
            //    if (disposing)
            //    {
            //        // Dispose managed resources.
            //        //Components.Dispose();
            //    }
            CloseHandle();
            //}
            //disposed = true;
        }

        public void Close()
        {
            // Calls the Dispose method without parameters.
            Dispose();
        }

        ~CognexDriverL()
        {
            Dispose(false);
        }

        private void DisConnect()
        {
            Stop();

            if (client == null)
                return;

            try
            {
                client.Close();
            }
            catch { }

            client = null;
            connected = false;
        }

        private bool CloseHandle()
        {
            try
            {
                DisConnect();
            }
            catch (Exception ex)
            {
                string sName = this.GetType().FullName;
                Logger.Write("Exception! +" + sName + "( " + ex.StackTrace + " )\n     Message: " + ex.Message);
            }
            return true;
        }


        private ByteBuilder receiveBuffer = new ByteBuilder();
        private void ReadData(ClientInfo ci, byte[] data, int len)
        {
            receiveBuffer.Add(data, 0, len);
            string text1 = Encoding.ASCII.GetString(receiveBuffer.Read(0, receiveBuffer.Length));

            if (this.PopulateReader(text1, "<Response>", "</Response>"))
            {
                if (OnDataReceived != null)
                {

                    string value =string.Empty;
                    string real_tag=string.Empty;
                    int status = ReadValue(out real_tag,  out value);

                    CameraArgsL arg = new CameraArgsL(status, value, mLastResponseString, real_tag);
                    OnDataReceived(this, arg);
                }

                receiveBuffer.Clear();
            
            }
           
        }


        private string current_tag = string.Empty;
        public bool SendCommand(string value, string tag)
        {
            bool ret = false;

            current_tag = tag;

            #region 更换工单电容检测相机联接不上,关闭tcp联接
            //if (value.StartsWith("LF"))
            //    try
            //    {
            //        listener = null;

            //        foreach (RemoteRunner _Runner in m_Runners)
            //        {
            //            _Runner.CloseEventHandler -= OnSessionClose;
            //            _Runner.NewCommandEventHandler -= OnNewCommand;
            //            _Runner.Stop();
            //        }

            //        m_Runners.Clear();
            //    }
            //    catch
            //    {
            //    }
            #endregion

            try
            {

                receiveBuffer.Clear();

                ByteBuilder b_s = new ByteBuilder();
                Byte[] value_arr = System.Text.Encoding.ASCII.GetBytes(value);

   
                if (value_arr.Length > 0)
                {
                    b_s.Add(System.Text.Encoding.ASCII.GetBytes(value));
                }
                else
                {
                    b_s.Add(new byte[] { 0 });
                }


                client.Send(b_s.Read(0, b_s.Length), b_s.Length);

                ret = true;
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
            return ret;
        }

        private bool PopulateReader(string xmlData, string element, string endElement)
        {
            int num1 = xmlData.LastIndexOf(element);
            if (num1 < 0)
            {
                return false;
            }
            int num2 = xmlData.LastIndexOf(endElement);
            if (num2 < 0)
            {
                return false;
            }
            this.mLastResponseString = this.PreProcessXml(xmlData.Substring(num1, (num2 - num1) + endElement.Length));
            try
            {
                XmlDocument document1 = new XmlDocument();
                document1.LoadXml(this.mLastResponseString);
                XmlNodeReader reader1 = new XmlNodeReader(document1);
                this.lastResponseReader = reader1;
            }
            catch (XmlException ex)
            {
                this.lastResponseReader = null;
            }
            return true;
        }


        private string PreProcessXml(string xml)
        {
            StringBuilder builder1 = new StringBuilder(xml);
            int num1 = 0;
            PreProcessStates states1 = PreProcessStates.LookingForLT;
            for (int num2 = 0; num2 < xml.Length; num2++)
            {
                char ch1 = xml[num2];
                switch (states1)
                {
                    case PreProcessStates.LookingForLT:
                        if (ch1 == '<')
                        {
                            states1 = PreProcessStates.LookingForAttrs;
                        }
                        goto Label_00C0;

                    case PreProcessStates.LookingForAttrs:
                        if (ch1 != ' ')
                        {
                            break;
                        }
                        states1 = PreProcessStates.LookingForEquals;
                        goto Label_00C0;

                    case PreProcessStates.LookingForEquals:
                        if (ch1 != '=')
                        {
                            goto Label_0066;
                        }
                        states1 = PreProcessStates.LookingForQuote;
                        goto Label_00C0;

                    case PreProcessStates.LookingForQuote:
                        if (ch1 != '"')
                        {
                            goto Label_007A;
                        }
                        states1 = PreProcessStates.LookingForAttrs;
                        goto Label_00C0;

                    case PreProcessStates.LookingForAttrEnd:
                        if (ch1 != ' ')
                        {
                            goto Label_00A8;
                        }
                        builder1.Insert(num2 + num1++, '"');
                        states1 = PreProcessStates.LookingForEquals;
                        goto Label_00C0;

                    default:
                        goto Label_00C0;
                }
                if (ch1 == '>')
                {
                    states1 = PreProcessStates.LookingForLT;
                }
                goto Label_00C0;
            Label_0066:
                if (ch1 == '>')
                {
                    states1 = PreProcessStates.LookingForLT;
                }
                goto Label_00C0;
            Label_007A:
                builder1.Insert(num2 + num1++, '"');
                states1 = PreProcessStates.LookingForAttrEnd;
                goto Label_00C0;
            Label_00A8:
                if (ch1 == '>')
                {
                    builder1.Insert(num2 + num1++, '"');
                    states1 = PreProcessStates.LookingForLT;
                }
            Label_00C0: ;
            }
            return builder1.ToString();
        }


        public int ReadValue( out string real_tag, out string value)
        {
            int status = -1;

            value = string.Empty;
            real_tag = string.Empty;

            if (this.lastResponseReader != null)
            {

                this.lastResponseReader.Read();
                if (this.lastResponseReader.Name == "Response") //Strings.NL("Response"))
                {

                    this.lastResponseReader.Read();
                    if (this.lastResponseReader.Name == "Status") //Strings.NL("Status"))
                    {

                        this.lastResponseReader.Read();
                        status = Convert.ToInt32(this.lastResponseReader.Value);
                        this.lastResponseReader.Read();

                        this.lastResponseReader.Read();
                        real_tag = this.lastResponseReader.Name;
                        this.lastResponseReader.Read();
                        value = this.lastResponseReader.Value;
                    }
                }
            }

            return status;
        }
        //private void DisConnect()
        //{
        //    if (client == null)
        //        return;

        //    if (!connected)
        //        return;

        //    client.Close();

        //    connected = false;
        //}

        //private bool CloseHandle()
        //{
        //    try
        //    {
        //        DisConnect();
        //    }
        //    catch (Exception ex)
        //    {
        //        string sName = this.GetType().FullName;
        //        Logger.Write("Exception! +" + sName + "( " + ex.StackTrace + " )\n     Message: " + ex.Message);
        //    }
        //    return true;
        //}



        //public bool Open()
        //{
        //    Connect();

        //    connected = true;

        //    return true;
        //}


        //private void Connect()
        //{
        //    IPAddress address = null;

        //    IPAddress.TryParse(ip_address, out address);
        //    if (this.connected)
        //    {
        //        this.DisConnect();
        //    }

        //    this.sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //    this.sock.Connect(new IPEndPoint(address, tcp_port));
            


        //    byte[] buffer1 =Encoding.ASCII.GetBytes(user + "\r\n");
        //    byte[] buffer2 = Encoding.ASCII.GetBytes(password + "\r\n");
        //    byte[] buffer3 = new byte[0x100];
        //    int num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
        //    string text1 = Encoding.ASCII.GetString(buffer3, 0, num1);
        //    int num2 = text1.IndexOf("User: "); //Strings.NL("User: "));
        //    if (num2 < 0)
        //    {
        //        num2 = text1.IndexOf("Welcome"); //Strings.NL("Welcome"));
        //        if (num2 >= 0)
        //        {
        //            num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
        //            text1 = text1 + Encoding.ASCII.GetString(buffer3, 0, num1);
        //            num2 = text1.IndexOf("User: ", num2);  //Strings.NL("User: "), num2);
        //        }
        //    }
        //    if (num2 < 0)
        //    {
        //        throw new Exception();
        //    }
        //    this.sock.Send(buffer1, buffer1.Length, SocketFlags.None);
        //    num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
        //    text1 = text1 + Encoding.ASCII.GetString(buffer3, 0, num1);
        //    num2 = text1.IndexOf("Password: ", num2); //Strings.NL("Password: "), num2);
        //    if (num2 < 0)
        //    {
        //        throw new Exception("Invalid Username"); //Strings.InvalidUsername(), true);
        //    }
        //    this.sock.Send(buffer2, buffer2.Length, SocketFlags.None);
        //    num1 = this.sock.Receive(buffer3, 0x100, SocketFlags.None);
        //    num2 = (text1 + Encoding.ASCII.GetString(buffer3, 0, num1)).IndexOf("User Logged In\r\n", num2); //Strings.NL("User Logged In\r\n"), num2);
        //    if (num2 < 0)
        //    {
        //        throw new Exception("Invalid Password"); //Strings.InvalidPassword(), false);
        //    }
        //   // this.SendCommand("PUT XML 2\r\n"); //Strings.NL("PUT XML 2\r\n")); // enables strict XML
        //    /*
        //    Command: GET FILELIST
                 
        //    <Response>
        //    <Status>1</Status>
        //    <NumFiles>1</NumFiles>
        //    <FileName ID="0">main.job</FileName>
        //    </Response>
        //    */
        //}


        //public void Dispose()
        //{
        //    Dispose(true);
        //    GC.SuppressFinalize(this);
        //}

        //protected virtual void Dispose(bool disposing)
        //{
        //    // Check to see if Dispose has already been called.
        //    //if (!this.disposed)
        //    //{
        //    //    // If disposing equals true, dispose all managed 
        //    //    // and unmanaged resources.
        //    //    if (disposing)
        //    //    {
        //    //        // Dispose managed resources.
        //    //        //Components.Dispose();
        //    //    }
        //    CloseHandle();
        //    //}
        //    //disposed = true;
        //}

        //public void Close()
        //{
        //    // Calls the Dispose method without parameters.
        //    Dispose();
        //}

        //~CognexDriverL()
        //{
        //    Dispose(false);
        //}


        //private void DisConnect()
        //{
        //    if (sock == null)
        //        return;

        //    if (this.sock.Connected)
        //    {
        //        this.sock.Shutdown(SocketShutdown.Both);
        //    }
        //    this.sock.Close();

        //    connected = false;
        //}

        //private bool CloseHandle()
        //{
        //    try
        //    {
        //        DisConnect();
        //    }
        //    catch (Exception ex)
        //    {
        //        string sName = this.GetType().FullName;
        //        Logger.Write("Exception! +" + sName + "( " + ex.StackTrace + " )\n     Message: " + ex.Message);
        //    }
        //    return true;
        //}



        //private void DisposeLastResponseReader()
        //{
        //    if (this.lastResponseReader != null)
        //    {
        //        this.lastResponseReader.Close();
        //        this.lastResponseReader = null;
        //    }
        //}


        //private byte[] GetRawResponse()
        //{
        //    byte[] buffer1 = null;
        //    if (this.sock.Available > 0)
        //    {
        //        int num1 = this.sock.Available;
        //        buffer1 = new byte[num1];
        //        int num2 = this.sock.Receive(buffer1, num1, SocketFlags.None);
        //        if (num2 >= num1)
        //        {
        //            return buffer1;
        //        }
        //        byte[] buffer2 = new byte[num2];
        //        Array.Copy(buffer1, 0, buffer2, 0, num2);
        //        buffer1 = buffer2;
        //    }

        //    return buffer1;
        //}


        //private string GetRawResponseLine()
        //{
        //    byte[] buffer1 = new byte[0x10];
        //    byte[] buffer2 = new byte[1];
        //    int num1 = 0;

        //    do
        //    {
        //        this.sock.Receive(buffer2, 1, SocketFlags.None);
        //        if (num1 == buffer1.Length)
        //        {
        //            buffer1 = buffer3;
        //        }
        //        buffer1[num1++] = buffer2[0];
        //    }
        //    while (buffer1[num1 - 1] != 10);
        //    return Encoding.UTF8.GetString(buffer1, 0, num1).Trim();
        //}

        //private byte[] GetResponseBytes(int numBytes)
        //{

        //    byte[] buffer1 = new byte[numBytes];
        //    int num1 = this.sock.Receive(buffer1, buffer1.Length, SocketFlags.None);

        //    return buffer1;
        //}

        //private void GetXmlResponse()
        //{
        //    StringBuilder builder1 = new StringBuilder("");
        //    this.mLastResponseString = "";
        //    this.lastResponseReader = null;
        //Label_001D:
        //    if (!this.WaitForResponseBytes(this.mTimeout))
        //    {
        //        return;//time out
        //    }
        //    byte[] buffer1 = this.GetRawResponse();
        //    if ((buffer1 == null) || (buffer1.Length <= 0))
        //    {
        //        goto Label_001D;
        //    }
        //    //builder1.Append(IspEncoding.GetEncoding().GetChars(buffer1, 0, buffer1.Length));
        //    builder1.Append(Encoding.UTF8.GetChars(buffer1, 0, buffer1.Length));
        //    string text1 = builder1.ToString();
        //    if (text1.IndexOf('<') < 0)
        //    {
        //        return; //throw new ("Xml Response Error", -1); //Strings.XmlResponseError(), -1);
        //    }
        //    //if (this.PopulateReader(text1, Strings.NL("<Response>"), Strings.NL("</Response>")))
        //    if (this.PopulateReader(text1, "<Response>", "</Response>"))
        //    {
        //        return;
        //    }
        //    goto Label_001D;
        //}


        //private bool PopulateReader(string xmlData, string element, string endElement)
        //{
        //    int num1 = xmlData.LastIndexOf(element);
        //    if (num1 < 0)
        //    {
        //        return false;
        //    }
        //    int num2 = xmlData.LastIndexOf(endElement);
        //    if (num2 < 0)
        //    {
        //        return false;
        //    }
        //    this.mLastResponseString = this.PreProcessXml(xmlData.Substring(num1, (num2 - num1) + endElement.Length));
        //    try
        //    {
        //        XmlDocument document1 = new XmlDocument();
        //        document1.LoadXml(this.mLastResponseString);
        //        XmlNodeReader reader1 = new XmlNodeReader(document1);
        //        this.lastResponseReader = reader1;
        //    }
        //    catch (XmlException ex)
        //    {
        //        this.lastResponseReader = null;
        //    }
        //    return true;
        //}


        //private string PreProcessXml(string xml)
        //{
        //    StringBuilder builder1 = new StringBuilder(xml);
        //    int num1 = 0;
        //    PreProcessStates states1 = PreProcessStates.LookingForLT;
        //    for (int num2 = 0; num2 < xml.Length; num2++)
        //    {
        //        char ch1 = xml[num2];
        //        switch (states1)
        //        {
        //            case PreProcessStates.LookingForLT:
        //                if (ch1 == '<')
        //                {
        //                    states1 = PreProcessStates.LookingForAttrs;
        //                }
        //                goto Label_00C0;

        //            case PreProcessStates.LookingForAttrs:
        //                if (ch1 != ' ')
        //                {
        //                    break;
        //                }
        //                states1 = PreProcessStates.LookingForEquals;
        //                goto Label_00C0;

        //            case PreProcessStates.LookingForEquals:
        //                if (ch1 != '=')
        //                {
        //                    goto Label_0066;
        //                }
        //                states1 = PreProcessStates.LookingForQuote;
        //                goto Label_00C0;

        //            case PreProcessStates.LookingForQuote:
        //                if (ch1 != '"')
        //                {
        //                    goto Label_007A;
        //                }
        //                states1 = PreProcessStates.LookingForAttrs;
        //                goto Label_00C0;

        //            case PreProcessStates.LookingForAttrEnd:
        //                if (ch1 != ' ')
        //                {
        //                    goto Label_00A8;
        //                }
        //                builder1.Insert(num2 + num1++, '"');
        //                states1 = PreProcessStates.LookingForEquals;
        //                goto Label_00C0;

        //            default:
        //                goto Label_00C0;
        //        }
        //        if (ch1 == '>')
        //        {
        //            states1 = PreProcessStates.LookingForLT;
        //        }
        //        goto Label_00C0;
        //    Label_0066:
        //        if (ch1 == '>')
        //        {
        //            states1 = PreProcessStates.LookingForLT;
        //        }
        //        goto Label_00C0;
        //    Label_007A:
        //        builder1.Insert(num2 + num1++, '"');
        //        states1 = PreProcessStates.LookingForAttrEnd;
        //        goto Label_00C0;
        //    Label_00A8:
        //        if (ch1 == '>')
        //        {
        //            builder1.Insert(num2 + num1++, '"');
        //            states1 = PreProcessStates.LookingForLT;
        //        }
        //    Label_00C0: ;
        //    }
        //    return builder1.ToString();
        //}


        //public short ReadStatusValue()
        //{
        //    short num2 = -255;

        //    if (this.lastResponseReader != null)
        //    {

        //        this.lastResponseReader.Read();
        //        if (this.lastResponseReader.Name == "Response") //Strings.NL("Response"))
        //        {

        //            this.lastResponseReader.Read();
        //            if (this.lastResponseReader.Name == "Status") //Strings.NL("Status"))
        //            {

        //                this.lastResponseReader.Read();
        //                short num1 = Convert.ToInt16(this.lastResponseReader.Value);
        //                this.lastResponseReader.Read();
        //                num2 = num1;
        //            }
        //        }
        //    }


        //    return num2;
        //}



        //public void ResetSystem()
        //{
        //    this.SendCommand("RT"); //Strings.NL("RT"));
        //    if (this.WaitForResponseBytes(0x3a98))
        //    {
        //        this.GetXmlResponse();
        //        short num1 = this.ReadStatusValue();

        //    }
        //    this.DisposeLastResponseReader();
        //    this.DisConnect();
        //}


        //public string SendCommand(string command)
        //{
        //    command = (command == null) ? "" : command;
        //    if (!this.connected)
        //    {
        //        return null;
        //    }
        //    if (!command.EndsWith("\r\n")) //Strings.NL("\r\n")))
        //    {
        //        command = command + "\r\n";
        //    }
        //    this.SendCommandNoWait(command);
        //    if (command.ToUpper() == "RT\r\n") //Strings.NL("RT\r\n"))
        //    {
        //        return null;
        //    }
        //    this.GetXmlResponse();
        //    return this.mLastResponseString;
        //}


        //internal void SendCommandNoWait(string command)
        //{
        //    if (!command.EndsWith("\r\n")) //Strings.NL("\r\n")))
        //    {
        //        command = command + "\r\n"; //Strings.NL("\r\n");
        //    }
        //    try
        //    {
        //        //byte[] buffer1 = IspEncoding.GetEncoding().GetBytes(command);
        //        byte[] buffer1 = Encoding.UTF8.GetBytes(command);
        //        this.sock.Send(buffer1, buffer1.Length, SocketFlags.None);
        //    }
        //    catch (Exception exception1)
        //    {

        //    }
        //}




        //private bool WaitForResponseBytes(int millisecondsTimeout)
        //{
        //    for (int num1 = millisecondsTimeout; num1 >= 0; num1 -= 0x19)
        //    {
        //        if (num1 >= 0x19)
        //        {
        //            Thread.Sleep(0x19);
        //        }
        //        else
        //        {
        //            Thread.Sleep(num1);
        //        }
        //        if (this.ResponseBytesAvailable)
        //        {
        //            return this.ResponseBytesAvailable;
        //        }
        //    }
        //    return this.ResponseBytesAvailable;
        //}



        //// Properties
        //public bool Connected
        //{
        //    get
        //    {
        //        if (!this.connected)
        //        {
        //            return false;
        //        }
        //        if (!this.sock.Connected)
        //        {
        //            this.disconnect();
        //            return false;
        //        }
        //        return true;
        //    }
        //}

        //[ComVisible(false)]
        //public XmlNodeReader LastResponseReader
        //{
        //    get
        //    {
        //        return this.lastResponseReader;
        //    }
        //}

        //public string LastResponseString
        //{
        //    get
        //    {
        //        return this.mLastResponseString;
        //    }
        //}

        //public bool NativeOnline
        //{
        //    get
        //    {
        //        bool flag1 = false;
        //        try
        //        {
        //            this.SendCommand("GO"); //Strings.NL("GO"));
        //            this.ReadStatusValue();
        //            try
        //            {
        //                this.lastResponseReader.Read();
        //                this.lastResponseReader.Read();

        //                flag1 = this.lastResponseReader.Value.Equals("1"); //Strings.NL("1"));
        //            }
        //            catch (Exception exception1)
        //            {

        //            }

        //        }
        //        finally
        //        {
        //            this.DisposeLastResponseReader();
        //        }
        //        return flag1;
        //    }
        //    set
        //    {
        //        try
        //        {
        //            string text1 = value ? "SO1" : "SO0"; //Strings.NL("SO1") : Strings.NL("SO0");
        //            this.SendCommand(text1);
        //            short num1 = this.ReadStatusValue();
        //            if (num1 == -6)
        //            {
        //                //NOT SUCCESS
        //            }
        //        }
        //        finally
        //        {
        //            this.DisposeLastResponseReader();
        //        }
        //    }
        //}






        private enum PreProcessStates
        {
            LookingForLT,
            LookingForAttrs,
            LookingForEquals,
            LookingForQuote,
            LookingForAttrEnd
        }


        //for tcp server
        private Thread listener = null;
        private int tcp_portS = 0;
        private ManualResetEvent m_StopEvent = new ManualResetEvent(false);
        private ManualResetEvent m_Connected = new ManualResetEvent(true);
        private List<RemoteRunner> m_Runners = new List<RemoteRunner>();
        private ManualResetEvent m_Result = new ManualResetEvent(false);
        string txResult = string.Empty;

        public string Result
        {
            get { return txResult; }
        }

        public bool IsRunning
        {
            get
            {
                return listener != null && listener.IsAlive;
            }
        }

        public bool Start()
        {
            if (IsRunning)
            {
                return true;
            }

            try
            {
                ManualResetEvent _Event = new ManualResetEvent(false);
                bool _Success = false;

                try
                {
                    listener = new Thread(new ParameterizedThreadStart(ListenThread));
                    m_StopEvent.Reset();
                    listener.Start(_Event);

                    try
                    {
                        while (!_Event.WaitOne(0) && listener.IsAlive)
                        {
                            Thread.Sleep(20);
                        }
                    }
                    catch
                    {
                        listener.Abort();
                        listener.Join();
                        throw;
                    }

                    _Success = listener.IsAlive;
                }
                catch
                {
                }

                if (!_Success)
                {
                    listener = null;
                }
                return _Success;
            }
            catch
            {
            }
            return false;
        }

        public void Stop()
        {
            if (!IsRunning)
            {
            }
            else
            {
                m_StopEvent.Set();

                try
                {
                    listener.Join();
                }
                catch
                {
                }
            }

            try
            {
                listener = null;
                
                foreach (RemoteRunner _Runner in m_Runners)
                {
                    _Runner.CloseEventHandler -= OnSessionClose;
                    _Runner.NewCommandEventHandler -= OnNewCommand;
                    _Runner.Stop();
                }

                m_Runners.Clear();
            }
            catch
            {
            }
        }

        private void ListenThread(Object objEvent)
        {
            Thread.CurrentThread.IsBackground = true;
            ManualResetEvent _Ready = (ManualResetEvent)objEvent;
            TcpListener _TcpListener = null;

            try
            {
                _TcpListener = new TcpListener(IPAddress.Any, tcp_portS);
                _TcpListener.Start();
                _Ready.Set();
            }
            catch
            {
                return;
            }

            try
            {
                while (WaitHandle.WaitAny(new WaitHandle[] { m_Connected, m_StopEvent }) == 0)
                {
                    m_Connected.Reset();
                    _TcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClientCallback), _TcpListener);
                }

                _TcpListener.Stop();
//                 m_Connected.WaitOne();
            }
            catch
            {
            }
        }

        private void DoAcceptTcpClientCallback(IAsyncResult ar)
        {
            try
            {
                TcpListener _Listener = (TcpListener)ar.AsyncState;
                TcpClient _Client = _Listener.EndAcceptTcpClient(ar);

                try
                {
                    RemoteRunner _Session = new RemoteRunner(_Client);

                    if (!_Session.Start())
                    {
                        _Client.Close();
                    }
                    else
                    {
                        try
                        {
                            _Session.CloseEventHandler += OnSessionClose;
                            _Session.NewCommandEventHandler += OnNewCommand;
                            m_Runners.Add(_Session);
                        }
                        catch
                        {
                            _Session.Stop();
                        }
                    }
                }
                catch
                {
                    _Client.Close();
                }
            }
            catch
            {
            }

             m_Connected.Set();
        }

        private void OnSessionClose(object objRunner)
        {
            RemoteRunner _Runner = (RemoteRunner)objRunner;
            m_Runners.Remove(_Runner);
        }

        public event RemoteRunnerEvents_OnNewCommand NewCommandEventHandler;

        protected virtual void OnNewCommandEventHandler(string txCommand)
        {
            if (NewCommandEventHandler != null)
            {
                NewCommandEventHandler(txCommand);
            }
        }

        private void OnNewCommand(object objRunner, string txCommand)
        {
            txResult = txCommand;

//             if (txResult.Length > 0)
//             {
                OnNewCommandEventHandler(txResult);
                m_Result.Set();
//             }
        }

        public void ResetResult()
        {
            m_Result.Reset();
        }

        public bool WaitResult(int timeout)
        {
            if (timeout < 0)
            {
                return m_Result.WaitOne();
            }
            else
            {
                return m_Result.WaitOne(timeout);
            }
        }
    }



    public class CameraArgsL : EventArgs
    {
        public readonly int Status;
        public readonly string Value;
        public readonly string ReceivedString;
        public readonly string Tag;

        public CameraArgsL(int sta, string va, string re, string tag)
        {
            Status = sta;
            Value = va;

            ReceivedString = re;

            Tag = tag;
        }

        public override string ToString()
        {
            return ReceivedString;
        }
    }
}
